package game

import (
	"gddgame.cc/galaxy/utils"
)

//go:generate msgp

// 对比数据来源
type SourceKey byte

//msgp:tuple Factor
type Factor struct {
	Source SourceKey `json:"source" msg:"source"`
	Key    string    `json:"key" msg:"key"`
	Value  int32     `json:"value" msg:"value"`
}

//msgp:tuple LanguageItem
type LanguageItem struct {
	Key   string `json:"key" msg:"key"`
	Value string `json:"value" msg:"value"`
}

//msgp IntAbilitySlice
type IntAbilitySlice []int

type IntAbilityMap map[int]int

func NewIntAbilitySlice(b []byte) IntAbilitySlice {
	ability := IntAbilitySlice{}
	_, _ = ability.UnmarshalMsg(b)
	return ability
}

func NewIntAbilitySliceBy(obj interface{}) IntAbilitySlice {
	v := utils.ToIntSlice(obj)
	return v
}

func (a *IntAbilitySlice) Bytes() []byte {
	b, _ := a.MarshalMsg(nil)
	return b
}

func (a IntAbilitySlice) ListToMap() IntAbilityMap {
	b := make(IntAbilityMap, len(a)/2)
	for i := 0; i < len(a); i += 2 {
		b[a[i]] = a[i+1]
	}
	return b
}

func (a IntAbilitySlice) ArrayIndex(index int) int {
	return a[index]
}

func (a IntAbilitySlice) GetArray(arrayMap map[int]int) []int {
	attrs := make([]int, len(arrayMap))
	for i := 0; i < len(a); i += 2 {
		id := a[i]
		if index, ok := arrayMap[id]; ok {
			attrs[index] = a[i+1]
		}
	}
	return attrs
}

func (b IntAbilityMap) MergeSlice(a IntAbilitySlice) {
	for i := 0; i < len(a); i += 2 {
		v, ok := b[a[i]]
		if !ok {
			v = 0
		}
		b[a[i]] = v + a[i+1]
	}
}

func (b IntAbilityMap) MergeMap(a IntAbilityMap) {
	for id, value := range a {
		v, ok := b[id]
		if !ok {
			v = 0
		}
		b[id] = v + value
	}
}

func (b IntAbilityMap) Append(id int, value int) {
	v, ok := b[id]
	if !ok {
		v = 0
	}
	b[id] = v + value
}

func (b IntAbilityMap) ToList() IntAbilitySlice {
	l := make(IntAbilitySlice, len(b)*2)
	i := 0
	for id, value := range b {
		l[i] = id
		l[i+1] = value
		i += 2
	}
	return l
}

func (b IntAbilityMap) Diff(a IntAbilityMap) map[int]int {
	d := map[int]int{}
	for id, value := range b {
		if v, ok := a[id]; ok {
			if v != value {
				d[id] = value
			}
		} else {
			d[id] = value
		}
	}
	for id, _ := range a {
		if _, ok := b[id]; !ok {
			d[id] = 0
		}
	}
	return d
}

func (b IntAbilityMap) Id(id int) int {
	return b[id]
}

func (b IntAbilityMap) GetArray(arrayMap map[int]int) []int {
	attrs := make([]int, len(arrayMap))
	for id, index := range arrayMap {
		attrs[index] = b[id]
	}
	return attrs
}

//msgp StringAbilitySlice
type StringAbilitySlice []string

func NewStringAbilitySlice(b []byte) StringAbilitySlice {
	ability := StringAbilitySlice{}
	_, _ = ability.UnmarshalMsg(b)
	return ability
}

func NewStringAbilitySliceBy(obj interface{}) StringAbilitySlice {
	v := utils.ToStringSlice(obj)
	return v
}

func (a *StringAbilitySlice) Bytes() []byte {
	b, _ := a.MarshalMsg(nil)
	return b
}

func (a StringAbilitySlice) Append(list []string) StringAbilitySlice {
	return append(a, list...)
}

func (a StringAbilitySlice) Duplicate() StringAbilitySlice {
	return utils.RemoveDuplicateString(a)
}

//msgp InfAbilitySlice
type InfAbilitySlice []interface{}

func NewInfAbilitySlice(b []byte) InfAbilitySlice {
	ability := InfAbilitySlice{}
	_, _ = ability.UnmarshalMsg(b)
	return ability
}

func NewInfAbilitySliceBy(obj interface{}) InfAbilitySlice {
	v := utils.ToInterfaceSlice(obj)
	return v
}

func (a *InfAbilitySlice) Bytes() []byte {
	b, _ := a.MarshalMsg(nil)
	return b
}

func (a InfAbilitySlice) Append(list []interface{}) InfAbilitySlice {
	return append(a, list...)
}

func (a InfAbilitySlice) Duplicate() InfAbilitySlice {
	return utils.RemoveDuplicateInf(a)
}
